Step Functionsの構築はAWS SAMを利用すると捗りそうです
AWS Serverless Application Model(以下、AWS SAM)は、サーバーレスアプリケーションのデプロイに特化した、CloudFormation(以下、CFn)の拡張機能です。
AWS SAMもテンプレートにリソースを定義し、デプロイの際はCFnが使用されます。AWS SAMはCFnに比べ、テンプレートを簡潔に定義できるのが特徴だったりします。
そんな、AWS SAMで、先日Step Functionsがサポートされました。
これにより、Lambda Functionとあわせ、呼び出し元(Step Functions)が定義できるようになりました。また、Step FunctionsのワークフローをAWS SAMテンプレート外に定義することで、Amazon States Language(以下、ASL)で記述できるので、AWS SAMを利用した構築に際し、新たな書式を覚える必要がありません。
AWS SAMでStep Functionsを構築したところ、積極的に利用していきたいと思いましたので、使用感などお伝えしたいと思います。
前提
AWS SAMでStep Functionsを扱うためには、AWS SAM CLI バージョン0.52.0以上が必要になります。AWS SAM CLIのインストールについては、以下を参照ください。
本エントリではAWS SAMについての詳細は割愛していますので、AWS SAMを詳しく求むという方は以下を参照してください。
やってみた
今回はLambda Functionを呼び出す、シンプルなステートマシンを構築してみたいと思います。
以下のような構成で、Lambda Functionのコードはfunctions
ディレクトリ配下のapp.py
で定義しました。ステートマシンのワークフローは、AWS SAMテンプレート内で定義するのではなくstatemachine
ディレクトリ配下のsfn.asl.json
で定義しました。
. ├── functions │ └── hello_world │ ├── app.py │ └── requirements.txt ├── statemachine │ └── sfn.asl.json └── template.yaml
それぞれ定義をみていきたいと思います。
ステートマシンから呼び出しされる、Lambda Functionのコードです。
def lambda_handler(event, context): print("Hello world")
ステートマシンのワークフローは、AWS SAMテンプレートから外出ししているので、マネジメントコンソールで定義する際と同様、ASL (Amazon States Language) で定義します。呼び出しを行うLambda Funtionの指定は、変数定義にすることで、AWS SAMテンプレート内で動的に指定することができます。
{ "StartAt": "hello world", "States": { "hello world": { "Type": "Task", "Resource": "${LambdaFunction}", "End": true } } }
AWS SAMテンプレートになります。ハイライトしている箇所がStep Functionsの定義です。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Parameters: StateMachineName: Description: Please type the Step Functions StateMachine Name. Type: String Default: 'sfn-sam-app-statemachine' LambdaFunctionName: Description: Please type the Lambda Function Name. Type: String Default: 'sfn-sam-app-function' Resources: LambdaFunction: Type: AWS::Serverless::Function Properties: FunctionName: !Sub ${LambdaFunctionName} CodeUri: functions/hello_world/ Handler: app.lambda_handler Runtime: python3.8 Timeout: 60 Role: !GetAtt LambdaFunctionRole.Arn LambdaFunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSStepFunctionsReadOnlyAccess StateMachine: Type: AWS::Serverless::StateMachine Properties: Name: !Sub ${StateMachineName} DefinitionUri: statemachine/sfn.asl.json DefinitionSubstitutions: LambdaFunction: !GetAtt LambdaFunction.Arn Role: !GetAtt StateMachineRole.Arn Logging: Level: ALL IncludeExecutionData: True Destinations: - CloudWatchLogsLogGroup: LogGroupArn: !GetAtt StateMachineLogGroup.Arn StateMachineLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName : !Join [ "", [ '/aws/states/', !Sub '${StateMachineName}', '-Logs' ] ] StateMachineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - states.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaRole - arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
簡単に補足します。
DefinitionUriプロパティでAWS SAMテンプレート外に記述したステートマシンのワークフロー定義を指定しています。DefinitionSubstitutionsプロパティで、ワークフロー内に定義した変数(${LambdaFunction}
)と、定義する値をマッピングしています。
これで構築の準備が完了です。
sam deployでデプロイを行います。オプション--guided
を指定することで、CFnスタック名など、必要なパラメータを対話形式で指定することが可能です。
$ sam deploy --guided Configuring SAM deploy ====================== Looking for samconfig.toml : Not found Setting default arguments for 'sam deploy' ========================================= Stack Name [sam-app]: AWS Region [us-east-1]: ap-northeast-1 Parameter StateMachineName [sfn-sam-app-statemachine]: Parameter LambdaFunctionName [sfn-sam-app-function]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: y #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: Save arguments to samconfig.toml [Y/n]:
プロンプトに従い必要な情報を入力していくと、変更されるリソース等が表示されます。変更セットを許可すればデプロイが開始されます。
Waiting for changeset to be created.. CloudFormation stack changeset --------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType --------------------------------------------------------------------------------------------------------------------------- + Add LambdaFunctionRole AWS::IAM::Role + Add LambdaFunction AWS::Lambda::Function + Add StateMachineLogGroup AWS::Logs::LogGroup + Add StateMachineRole AWS::IAM::Role + Add StateMachine AWS::StepFunctions::StateMachine --------------------------------------------------------------------------------------------------------------------------- Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:changeSet/samcli-deploy1592909667/0face98a-4e59-4dd9-be36-f9662d24d0c9 Previewing CloudFormation changeset before deployment ====================================================== Deploy this changeset? [y/N]: y
作成されたリソース等が表示され、しばらくするとデプロイが完了します。
2020-06-23 19:59:05 - Waiting for stack create/update to complete CloudFormation events from changeset ------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason ------------------------------------------------------------------------------------------------------------------------- CREATE_IN_PROGRESS AWS::Logs::LogGroup StateMachineLogGroup - CREATE_IN_PROGRESS AWS::IAM::Role StateMachineRole - CREATE_IN_PROGRESS AWS::IAM::Role LambdaFunctionRole - CREATE_IN_PROGRESS AWS::Logs::LogGroup StateMachineLogGroup Resource creation Initiated CREATE_IN_PROGRESS AWS::IAM::Role StateMachineRole Resource creation Initiated CREATE_IN_PROGRESS AWS::IAM::Role LambdaFunctionRole Resource creation Initiated CREATE_COMPLETE AWS::Logs::LogGroup StateMachineLogGroup - CREATE_COMPLETE AWS::IAM::Role StateMachineRole - CREATE_COMPLETE AWS::IAM::Role LambdaFunctionRole - CREATE_IN_PROGRESS AWS::Lambda::Function LambdaFunction - CREATE_IN_PROGRESS AWS::Lambda::Function LambdaFunction Resource creation Initiated CREATE_COMPLETE AWS::Lambda::Function LambdaFunction - CREATE_IN_PROGRESS AWS::StepFunctions::StateMac StateMachine - hine CREATE_COMPLETE AWS::StepFunctions::StateMac StateMachine - hine CREATE_IN_PROGRESS AWS::StepFunctions::StateMac StateMachine Resource creation Initiated hine CREATE_COMPLETE AWS::CloudFormation::Stack sam-app - ------------------------------------------------------------------------------------------------------------------------- Successfully created/updated stack - sam-app in ap-northeast-1
デプロイが完了していますので、マネジメントコンソールからもステートマシンの作成を確認することができます。
今回の構成でワークフローを変更する際は、sfn.asl.json
を更新します。
{ "StartAt": "hello world", "States": { "hello world": { "Type": "Task", "Resource": "${LambdaFunction}", "Next": "succeed", "Catch": [ { "ErrorEquals": [ "States.ALL" ], "Next": "fail" } ] }, "succeed": { "Type": "Succeed" }, "fail": { "Type": "Fail", "Error": "ErrorCode 100", "Cause": "There is Error." } } }
再度、デプロイを行えば環境に反映されます。
$ sam deploy (省略) CloudFormation stack changeset --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Operation LogicalResourceId ResourceType --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Modify StateMachine AWS::StepFunctions::StateMachine --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- (省略) CloudFormation events from changeset ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- UPDATE_IN_PROGRESS AWS::StepFunctions::StateMachine StateMachine - UPDATE_COMPLETE AWS::StepFunctions::StateMachine StateMachine - UPDATE_COMPLETE_CLEANUP_IN_PROGRESS AWS::CloudFormation::Stack sam-app - UPDATE_COMPLETE AWS::CloudFormation::Stack sam-app - ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Successfully created/updated stack - sam-app in ap-northeast-1
変更が反映されたことが確認できました。
おまけ
テンプレート内のLambda Functionから、StepFunctionsを操作したいといった時には、 該当するステートマシンのARNをLambda Functionの環境変数に設定したり...なんてことがあると思いますが、今回のような構成でそれをやってしまうと、circular dependencies(循環参照)のエラーとなります。
StepFunctionsでは実行中に使用できるContext オブジェクトがあり、ステートマシンのARNも取得することができます。 循環参照が発生した時でもいいので、Context オブジェクトで値がとれるということを、頭の片隅にでも入れておいていただければ幸いです。
最後に
Step Functionsがサポートされたことにより、Lambda Functionとあわせ、呼び出し元(Step Functions)も定義できますので、 AWS SAMのベストプラクティスにあるような管理が行え、 開発、運用が行いやすくなるのではないでしょうか。
CFnに馴染みのある方であれが、AWS SAM自体はスムーズに利用できると思いますので、Step Functionsを構築する際はAWS SAMの利用も検討してみてはいかがでしょうか。